#define _CRT_SECURE_NO_WARNINGS 1

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */

class BSTIterator
{
public:
    BSTIterator(TreeNode* root)
        : _root(root)
        , _cur(nullptr)
        , _final(nullptr)
    {
        _final = FindRight(_root);
    }

    int next()
    {
        if (_cur == nullptr)
        {
            _cur = FindLeft(_root);
            return _cur->val;
        }
        else
        {
            if (_cur->right != nullptr)
            {
                _cur = FindLeft(_cur->right);
                return _cur->val;
            }
            else
            {
                std::vector<TreeNode*> path;
                GetPath(_root, _cur, path);

                TreeNode* child = path.back();
                path.pop_back();

                while (!path.empty())
                {
                    TreeNode* parent = path.back();
                    path.pop_back();

                    if (parent->left == child)
                    {
                        _cur = parent;
                        return parent->val;
                    }

                    child = parent;
                }

                return INT_MIN;
            }
        }
    }

    bool hasNext()
    {
        return !(_cur == _final);
    }

private:
    TreeNode* FindRight(TreeNode* root)
    {
        TreeNode* cur = root;
        while (cur->right) {
            cur = cur->right;
        }
        return cur;
    }

    TreeNode* FindLeft(TreeNode* root)
    {
        TreeNode* cur = root;
        while (cur->left) {
            cur = cur->left;
        }
        return cur;
    }

    void GetPath(TreeNode* root, TreeNode* target, std::vector<TreeNode*>& path)
    {
        TreeNode* cur = root;

        while (cur != target)
        {
            path.push_back(cur);

            if (cur->val > target->val) {
                cur = cur->left;
            }
            else {
                cur = cur->right;
            }
        }

        path.push_back(cur);
    }

    TreeNode* _root;
    TreeNode* _cur;
    TreeNode* _final;
};